package  
{
	import CharacterTraits.*;
	import org.flixel.FlxPath;
	import org.flixel.FlxPoint;
	import org.flixel.FlxRect;
	import org.flixel.FlxText;
	import org.flixel.FlxTilemap;
	import org.flixel.plugin.photonstorm.FlxExtendedSprite;
	import org.flixel.FlxG;
	import Data.Color;
	import ConversationClasses.ConversationHistory;
	import StoryGeneration.Location;
	import StoryGeneration.Relationship;
	
	public class Character extends FlxExtendedSprite
	{
		public static const TALK_RANGE:Number = 80;
		public static const ACTION_IDLE:int = 0;
		public static const ACTION_MOVING:int = 1;
		public static const ACTION_TALKING:int = 2;
		
		public var name:Name;
		public var age:uint;
		public var gender:String;
		public var hairColor:String;
		public var eyeColor:String;
		public var personality:Personality;
		public var conversationHistory:ConversationHistory;
		public var relationship:String;
		public var map:FlxTilemap;
		
		public var looking:String = "";
		public var currentAction:int;
		public var currentRoom:Room;
		private var tempFrameNum:Number;
		
		private var lastX:Number;
		private var lastY:Number;
		private var deltaX:Number;
		private var deltaY:Number;
		private var idleTime:Number;
		
		public function Character(X:Number, Y:Number, characterName:Name, characterAge:uint, characterGender:String, characterHairColor:String, characterEyeColor:String, characterPersonality:Personality, characterRelationship:String, tilemap:FlxTilemap, SimpleGraphic:Class) 
		{
			super(X, Y);
			
			immovable = true;
			
			CharacterSetup(characterName, characterAge, characterGender, characterHairColor, characterEyeColor, characterPersonality, characterRelationship);
			
			if (SimpleGraphic != null)
			{
				loadGraphic(SimpleGraphic, true, false, 30, 30);
			}
			
			conversationHistory = new ConversationHistory();
			
			createAnimations();
			
			//start all NPCs looking down and idle
			looking = "down";
			play("idle_down");
			currentAction = ACTION_IDLE;
			
			map = tilemap;
			idleTime = 3;
			
			createAnimations();
		}
		
		override public function update():void 
		{
			super.update();
			
			decide();
			
			deltaX = x - lastX;
			deltaY = y - lastY;
			lastX = x;
			lastY = y;
			
			updateAnimations();
		}
		
		private function CharacterSetup(characterName:Name, characterAge:uint, characterGender:String, characterHairColor:String, characterEyeColor:String, characterPersonality:Personality, characterRelationship:String):void
		{
			name = characterName;
			
			age = characterAge;
			
			gender = characterGender;
			
			hairColor = characterHairColor;
			
			eyeColor = characterEyeColor;
			
			personality = characterPersonality;
			
			relationship = characterRelationship;
		}
		
		private function createAnimations():void 
		{
			addAnimation("idle_up", [4]);
			addAnimation("idle_left", [10]);
			addAnimation("idle_down", [1]);
			addAnimation("idle_right", [7]);
			addAnimation("idle_upRight", [13]);
			addAnimation("idle_downLeft", [22]);
			addAnimation("idle_upLeft", [16]);
			addAnimation("idle_downRight", [19]);
			addAnimation("walk_up", [5, 4, 3, 4], 6); // 5 = frames per second for this animation
			addAnimation("walk_left", [11, 10, 9, 10], 6);
			addAnimation("walk_down", [0, 1, 2, 1], 6);
			addAnimation("walk_right", [6, 7, 8, 7], 6);
			addAnimation("walk_upRight", [12, 13, 14, 13], 6);
			addAnimation("walk_downLeft", [23, 22, 21, 22], 6);
			addAnimation("walk_upLeft", [17, 16, 15, 16], 6);
			addAnimation("walk_downRight", [18, 19, 20, 19], 6);
		}
		
		private function updateAnimations():void
		{
			if (deltaX == 0 && deltaY < 0)
			{
				if (looking != "up")
				{
					tempFrameNum = frame;
				}
				play("walk_up", false, false);
				looking = "up";
			}
			else if (deltaX > 0 && deltaY == 0)
			{
				if (looking != "right")
				{
					tempFrameNum = frame;
				}
				play("walk_right", false, false);
				looking = "right";
			}
			else if (deltaX == 0 && deltaY > 0)
			{
				if (looking != "down")
				{
					tempFrameNum = frame;
				}
				play("walk_down", false, false);
				looking = "down";
			}
			else if (deltaX < 0 && deltaY == 0)
			{
				if (looking != "left")
				{
					tempFrameNum = frame;
				}
				play("walk_left", false, false);
				looking = "left";
			}
			else if (deltaX > 0 && deltaY < 0)
			{
				if (looking != "upRight")
				{
					tempFrameNum = frame;
				}
				play("walk_upRight", false, false);
				looking = "upRight";
			}
			else if (deltaX > 0 && deltaY > 0)
			{
				if (looking != "downRight")
				{
					tempFrameNum = frame;
				}
				play("walk_downRight", false, false);
				looking = "downRight";
			}
			else if (deltaX < 0 && deltaY > 0)
			{
				if (looking != "downLeft")
				{
					tempFrameNum = frame;
				}
				play("walk_downLeft", false, false);
				looking = "downLeft";
			}
			else if (deltaX < 0 && deltaY < 0)
			{
				if (looking != "upLeft")
				{
					tempFrameNum = frame;
				}
				play("walk_upLeft", false, false);
				looking = "upLeft";
			}
			else if (deltaX == 0 && deltaY == 0)
			{
				if (looking == "right")
					play("idle_right");
				else if (looking == "down")
					play("idle_down");
				else if (looking == "left")
					play("idle_left");
				else if (looking == "upRight")
					play("idle_upRight");
				else if (looking == "downRight")
					play("idle_downRight");
				else if (looking == "downLeft")
					play("idle_downLeft");
				else if (looking == "upLeft")
					play("idle_upLeft");
				else
					play("idle_up");
			}
		}
		
		private function decide():void
		{
			// Decide what to do next.
			currentRoom = getCurrentRoom();
			
			// If we are talking, make sure we just stand still.
			if (currentAction == ACTION_TALKING)
			{
				stop();
			}
			else if (currentAction == ACTION_IDLE)
			{
				if (idleTime > 0)
				{
					idleTime -= FlxG.elapsed;
				}
				else
				{
					if (FlxG.random() < .05)
					{
						switch (Math.floor(FlxG.random() * 9))
						{
							case 0:
								currentRoom = BaseGameState.Bathroom;
								break;
							case 1:
								currentRoom = BaseGameState.BilliardRoom;
								break;
							case 2:
								currentRoom = BaseGameState.DiningRoom;
								break;
							case 3:
								currentRoom = BaseGameState.Foyer;
								break;
							case 4:
								currentRoom = BaseGameState.Gallery;
								break;
							case 5:
								currentRoom = BaseGameState.Kitchen;
								break;
							case 6:
								currentRoom = BaseGameState.Lounge;
								break;
							case 7:
								currentRoom = BaseGameState.MasterBedroom;
								break;
							case 8:
								currentRoom = BaseGameState.ServantsQuarters;
								break;
							default:
								currentRoom = BaseGameState.Bathroom;
						}
					}
					if (currentRoom)
					{
						var location:Location = new Location(0, 0, BaseGameState.Bathroom);
						
						switch (currentRoom)
						{
							case (BaseGameState.Bathroom):
								location = Location(FlxG.getRandom(BaseGameState.BathroomArray));
								break;
							case (BaseGameState.BilliardRoom):
								location = Location(FlxG.getRandom(BaseGameState.BilliardRoomArray));
								break;
							case (BaseGameState.DiningRoom):
								location = Location(FlxG.getRandom(BaseGameState.DiningRoomArray));
								break;
							case (BaseGameState.Foyer):
								location = Location(FlxG.getRandom(BaseGameState.FoyerArray));
								break;
							case (BaseGameState.Gallery):
								location = Location(FlxG.getRandom(BaseGameState.GalleryArray));
								break;
							case (BaseGameState.Kitchen):
								location = Location(FlxG.getRandom(BaseGameState.KitchenArray));
								break;
							case (BaseGameState.Lounge):
								location = Location(FlxG.getRandom(BaseGameState.LoungeArray));
								break;
							case (BaseGameState.MasterBedroom):
								location = Location(FlxG.getRandom(BaseGameState.MasterBedroomArray));
								break;
							case (BaseGameState.ServantsQuarters):
								location = Location(FlxG.getRandom(BaseGameState.ServantsQuartersArray));
								break;
							default:
								FlxG.log("Bad current room!")
								break;
						}
						moveTo(new FlxPoint(location.x, location.y));
						
					}
					
				}
			}
			else if (currentAction == ACTION_MOVING)
			{
				if (pathSpeed == 0)
				{
					idle();
					stop();
				}
			}
			
		}
		
		public function moveTo(target:FlxPoint):void
		{
			if (currentAction == ACTION_IDLE)
			{	
				//Find path to goal
				var path:FlxPath = map.findPath(new FlxPoint(x + width / 2, y + height / 2), target);
				
				//Tell unit to follow path
				followPath(path);
				currentAction = ACTION_MOVING;
			}
		}
		
		public function idle():void
		{
			currentAction = ACTION_IDLE;
			idleTime = FlxG.random() + .5;
		}
		
		private function stop():void
		{
			//Stop unit and destroy unit path
			stopFollowingPath(true);
			velocity.x = velocity.y = 0;
		}
		
		private function getCurrentRoom():Room
		{
			if (checkRoom(BaseGameState.Foyer))
			{
				return BaseGameState.Foyer;
			}
			if (checkRoom(BaseGameState.Kitchen))
			{
				return BaseGameState.Kitchen;
			}
			if (checkRoom(BaseGameState.Lounge))
			{
				return BaseGameState.Lounge;
			}
			if (checkRoom(BaseGameState.Gallery))
			{
				return BaseGameState.Gallery;
			}
			if (checkRoom(BaseGameState.Bathroom))
			{
				return BaseGameState.Bathroom;
			}
			if (checkRoom(BaseGameState.DiningRoom))
			{
				return BaseGameState.DiningRoom;
			}
			if (checkRoom(BaseGameState.ServantsQuarters))
			{
				return BaseGameState.ServantsQuarters;
			}
			if (checkRoom(BaseGameState.BilliardRoom))
			{
				return BaseGameState.BilliardRoom;
			}
			if (checkRoom(BaseGameState.MasterBedroom))
			{
				return BaseGameState.MasterBedroom;
			}
			
			return null;
		}
		
		private function checkRoom(room:Room):Boolean
		{
			var temp:Boolean;
			
			if ((x <= room.x + room.width) && (x + width >= room.x) && 
				(y <= room.y + room.height) && (y + height >= room.y))
			{
				temp = true;
			}
			else
			{
				room.Toggle(false);
				temp = false;
			}
			
			return temp;
		}
		
	}
}